﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using YJKRevitArea.AreaSet;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YArchitech.Controls;
using YArchitech.Revit;
using YArchitech.Revit.RevitExtension;
using YJKArchBaseCode.OutWallSearch;
using YJKArchUtils.Utils;
using YJKRevitView;

namespace YJKInspectModel.ModelValidation.AdjoinFireZone
{
	public class FindCrossPointsHorFireZone
	{
		public FindCrossPointsHorFireZone(Autodesk.Revit.DB.Document doc, ViewPlan viewPlan, UIApplication uiApp)
		{
			this.m_curDoc = doc;
			this.m_curViewPlan = viewPlan;
			this.m_uiApp = uiApp;
		}

		public List<Wall> GetOutWalls()
		{
			return this.m_lstOutWalls;
		}

		public Dictionary<XYZ, XYZ> GetCrossPoints()
		{
			return this.m_dictCrossPoints;
		}

		public bool ManageCurViewPlanCrossPoints()
		{
			this.m_lstArea = FindCrossPointsHorFireZone.GetFireAreasCurViewPlan(this.m_curViewPlan, this.m_curDoc);
			if (this.m_lstArea.Count == 0)
			{
				return false;
			}
			this.m_lstOutWalls = FindCrossPointsHorFireZone.GetOutWallsCurViewPlan(this.m_curViewPlan, this.m_curDoc, this.m_uiApp);
			if (this.m_lstOutWalls.Count == 0)
			{
				return false;
			}
			this.m_dictCrossPoints = FindCrossPointsHorFireZone.FindAllCrossPoints(this.m_lstArea, this.m_lstOutWalls);
			return this.m_dictCrossPoints.Count != 0;
		}

		public static ViewPlan GetViewPlanFromName(string strViewPlanName, Autodesk.Revit.DB.Document doc)
		{
			foreach (ViewPlan viewPlan in FloorSelectManager.GetAllFireAreaViewPlan(doc))
			{
				if (viewPlan.Name == strViewPlanName)
				{
					return viewPlan;
				}
			}
			return null;
		}

		public static List<Area> GetFireAreasCurViewPlan(ViewPlan curViewPlan, Autodesk.Revit.DB.Document doc)
		{
			List<Area> list = new List<Area>();
			list = YJKRevitArea.AreaSet.Common.FilterFireAreas(doc, curViewPlan.Id);
			foreach (RevitLinkInstance revitLinkInstance in YJKArchUtils.Utils.Common.GetAllRevitLinkInstancesInDoc(doc))
			{
				Document linkDocument = revitLinkInstance.GetLinkDocument();
				if (linkDocument != null)
				{
					ViewPlan viewPlanFromName = FindCrossPointsHorFireZone.GetViewPlanFromName(curViewPlan.Name, linkDocument);
					if (viewPlanFromName != null)
					{
						List<Area> list2 = YJKRevitArea.AreaSet.Common.FilterFireAreas(linkDocument, viewPlanFromName.Id);
						if (list2 != null && list2.Count != 0)
						{
							for (int i = 0; i < list2.Count; i++)
							{
								if (FindCrossPointsHorFireZone.IsAreaExistInList(list2[i], list))
								{
									list2.RemoveAt(i);
									i--;
								}
							}
							list.AddRange(list2);
						}
					}
				}
			}
			return list;
		}

		public static List<Wall> GetOutWallsCurViewPlan(ViewPlan curViewPlan, Autodesk.Revit.DB.Document doc, UIApplication uiApp)
		{
			List<Wall> list = new List<Wall>();
			if (!OutWallFilter.Search(doc, curViewPlan.Id, ref list, true, true))
			{
				return list;
			}
			foreach (RevitLinkInstance revitLinkInstance in YJKArchUtils.Utils.Common.GetAllRevitLinkInstancesInDoc(doc))
			{
				Document linkDocument = revitLinkInstance.GetLinkDocument();
				if (linkDocument != null)
				{
					ViewPlan viewPlanFromName = FindCrossPointsHorFireZone.GetViewPlanFromName(curViewPlan.Name, linkDocument);
					if (viewPlanFromName != null)
					{
						List<Wall> list2 = new List<Wall>();
						if (FindCrossPointsHorFireZone.GetLinkDocOutWall(ref list2, viewPlanFromName.Id, linkDocument, uiApp) && list2.Count != 0)
						{
							list.AddRange(list2);
						}
					}
				}
			}
			return list;
		}

		public static bool GetLinkDocOutWall(ref List<Wall> lstOutWallLinkDoc, ElementId viewId, Autodesk.Revit.DB.Document docLink, UIApplication uiApp)
		{
			string pathName = docLink.PathName;
			if (!File.Exists(pathName))
			{
				return false;
			}
			IEnumerable<Element> enumerable = new FilteredElementCollector(docLink, viewId).OfClass(typeof(Wall)).ToElements();
			List<Wall> list = new List<Wall>();
			foreach (Element element in enumerable)
			{
				Wall wall = element as Wall;
				if (wall.ParametersMap.Contains("已附着顶部") || wall.ParametersMap.Contains("Top is Attached"))
				{
					list.Add(wall);
				}
			}
			Document document = null;
			string text = Path.GetTempPath();
			text += "tempLinkDoc.rvt";
			try
			{
				File.Copy(pathName, text, true);
			}
			catch (Exception ex)
			{
				YJKMessageBox.Information(ex.Message);
				return false;
			}
			try
			{
				document = uiApp.Application.OpenDocumentFile(text);
			}
			catch (Exception)
			{
				YJKMessageBox.Information("文档打开出错");
				return false;
			}
			List<Wall> list2 = new List<Wall>();
			if (!OutWallFilter.Search(document, viewId, ref list2, false, true))
			{
				document.Close();
				return false;
			}
			foreach (Wall wall2 in list2)
			{
				foreach (Wall wall3 in list)
				{
					if (wall2.Id == wall3.Id)
					{
						lstOutWallLinkDoc.Add(wall3);
						break;
					}
				}
			}
			document.Close();
			return true;
		}

		public static List<Curve> GetWallCurvesFromAreaBounardy(List<Curve> lstAreaCurves, List<Wall> lstOutWall)
		{
			List<Curve> list = new List<Curve>();
			if (lstAreaCurves == null)
			{
				return list;
			}
			List<Curve> list2 = new List<Curve>();
			foreach (Curve curve in lstAreaCurves)
			{
				Wall wall = null;
				if (FindCrossPointsHorFireZone.IsCurveOnWallOutline(ref wall, curve, lstOutWall))
				{
					list.Add((wall.Location as LocationCurve).Curve);
				}
				else
				{
					list2.Add(curve);
				}
			}
			for (int i = 0; i < list2.Count; i++)
			{
				Curve curve2 = list2[i];
				foreach (Curve curve3 in list)
				{
					foreach (XYZ xyz in new List<XYZ>
					{
						curve3.GetEndPoint(0),
						curve3.GetEndPoint(1)
					})
					{
						if (FindCrossPointsHorFireZone.IsPointOnCurveMid(xyz, curve2))
						{
							FindCrossPointsHorFireZone.ChangeCurveEndPoint(ref curve2, xyz);
						}
					}
				}
				list.Add(curve2);
			}
			return list;
		}

		public static void ChangeCurveEndPoint(ref Curve curve, XYZ ptOn)
		{
			XYZ xyz = curve.GetEndPoint(0);
			XYZ xyz2 = curve.GetEndPoint(1);
			if (curve as Line != null)
			{
				if (xyz.DistanceTo(ptOn) < xyz2.DistanceTo(ptOn))
				{
					xyz = ptOn;
				}
				else
				{
					xyz2 = ptOn;
				}
				curve = Line.CreateBound(xyz, xyz2);
				return;
			}
			XYZ xyz3 = curve.Evaluate(0.5, true);
			if (xyz.DistanceTo(ptOn) < xyz2.DistanceTo(ptOn))
			{
				xyz = ptOn;
			}
			else
			{
				xyz2 = ptOn;
			}
			curve = Arc.Create(xyz, xyz2, xyz3);
		}

		public static List<Curve> GetAreaBounardyCurves(Area curArea)
		{
			List<Curve> list = new List<Curve>();
			foreach (IList<BoundarySegment> list2 in curArea.GetBoundarySegments(new SpatialElementBoundaryOptions
			{
                SpatialElementBoundaryLocation = (SpatialElementBoundaryLocation)1
			}))
			{
				IEnumerator<BoundarySegment> enumerator2 = list2.GetEnumerator();
				{
					while (enumerator2.MoveNext())
					{
						BoundarySegment segment = enumerator2.Current;
						list.Add(segment.GetCurve());
					}
					break;
				}
			}
			return list;
		}

		public static Dictionary<XYZ, XYZ> FindAllCrossPoints(List<Area> lstArea, List<Wall> lstOutWall)
		{
			Dictionary<XYZ, XYZ> dictionary = new Dictionary<XYZ, XYZ>();
			Dictionary<Area, List<Curve>> dictionary2 = new Dictionary<Area, List<Curve>>();
			foreach (Area area in lstArea)
			{
				List<Curve> wallCurvesFromAreaBounardy = FindCrossPointsHorFireZone.GetWallCurvesFromAreaBounardy(FindCrossPointsHorFireZone.GetAreaBounardyCurves(area), lstOutWall);
				dictionary2.Add(area, wallCurvesFromAreaBounardy);
			}
			for (int i = 0; i < dictionary2.Count - 1; i++)
			{
				List<Curve> list = new List<Curve>();
				List<Curve> list2 = new List<Curve>();
				list.AddRange(dictionary2.ElementAt(i).Value);
				list2.AddRange(list);
				FindCrossPointsHorFireZone.DeleteNotOnOutWallCurves(ref list, lstOutWall);
				for (int j = i + 1; j < dictionary2.Count; j++)
				{
					List<Curve> list3 = new List<Curve>();
					list3.AddRange(dictionary2.ElementAt(j).Value);
					FindCrossPointsHorFireZone.DeleteNotOnOutWallCurves(ref list3, lstOutWall);
					Dictionary<XYZ, XYZ> crossOnEndCurveInfo = FindCrossPointsHorFireZone.GetCrossOnEndCurveInfo(list, list3, list2);
					if (crossOnEndCurveInfo.Count > 0)
					{
						foreach (KeyValuePair<XYZ, XYZ> keyValuePair in crossOnEndCurveInfo)
						{
							if (!FindCrossPointsHorFireZone.IsExistPointInDict(keyValuePair.Key, dictionary))
							{
								dictionary.Add(keyValuePair.Key, keyValuePair.Value);
							}
						}
					}
				}
			}
			return dictionary;
		}

		public static bool IsExistPointInDict(XYZ pt, Dictionary<XYZ, XYZ> dictCrossPtsWithVect)
		{
			foreach (KeyValuePair<XYZ, XYZ> keyValuePair in dictCrossPtsWithVect)
			{
				if (Geometry.IsEqual(keyValuePair.Key, pt))
				{
					return true;
				}
			}
			return false;
		}

		public static bool IsAreaExistInList(Area area, List<Area> lstArea)
		{
			foreach (Area area2 in lstArea)
			{
				if (FindCrossPointsHorFireZone.IsEqualArea(area, area2))
				{
					return true;
				}
			}
			return false;
		}

		public static bool IsEqualArea(Area area1, Area area2)
		{
			if (!Geometry.IsEqual(area1.Area, area2.Area))
			{
				return false;
			}
			List<Curve> list = new List<Curve>();
			IEnumerable<IList<BoundarySegment>> boundarySegments = area1.GetBoundarySegments(new SpatialElementBoundaryOptions());
			double num = 0.0;
			foreach (IList<BoundarySegment> list2 in boundarySegments)
			{
				foreach (BoundarySegment segment in list2)
				{
					Curve curve = segment.GetCurve();
					list.Add(curve);
					num += curve.Length;
				}
			}
			List<Curve> list3 = new List<Curve>();
			double num2 = 0.0;
			foreach (IList<BoundarySegment> list4 in area2.GetBoundarySegments(new SpatialElementBoundaryOptions()))
			{
				foreach (BoundarySegment segment2 in list4)
				{
					list3.Add(segment2.GetCurve());
					Curve curve2 = segment2.GetCurve();
					list3.Add(curve2);
					num2 += curve2.Length;
				}
			}
			if (list.Count != list3.Count)
			{
				return false;
			}
			if (!Geometry.IsEqual(num, num2))
			{
				return false;
			}
			foreach (Curve curve3 in list)
			{
				bool flag = false;
				foreach (Curve curve4 in list3)
				{
					if (FindCrossPointsHorFireZone.IsSameCurves(curve3, curve4))
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					return false;
				}
			}
			return true;
		}

		public static bool IsSameCurves(Curve curve1, Curve curve2)
		{
			XYZ hyendPoint = curve1.GetEndPoint(0);
			XYZ hyendPoint2 = curve1.GetEndPoint(1);
			XYZ pt = curve1.Evaluate(0.5, true);
			XYZ hyendPoint3 = curve2.GetEndPoint(0);
			XYZ hyendPoint4 = curve2.GetEndPoint(1);
			XYZ pt2 = curve2.Evaluate(0.5, true);
			return Geometry.IsEqual(pt, pt2) && ((Geometry.IsEqual(hyendPoint, hyendPoint3) && Geometry.IsEqual(hyendPoint2, hyendPoint4)) || (Geometry.IsEqual(hyendPoint, hyendPoint4) && Geometry.IsEqual(hyendPoint2, hyendPoint3)));
		}

		public static Dictionary<XYZ, XYZ> GetCrossOnEndCurveInfo(List<Curve> lstCurveCur, List<Curve> lstCurveOther, List<Curve> lstCurveTolCur)
		{
			for (int i = 0; i < lstCurveTolCur.Count; i++)
			{
				if (lstCurveCur.Contains(lstCurveTolCur[i]))
				{
					lstCurveTolCur.RemoveAt(i);
					i--;
				}
			}
			Dictionary<XYZ, XYZ> dictionary = new Dictionary<XYZ, XYZ>();
			foreach (Curve curve in lstCurveCur)
			{
				curve.GetEndPoint(0);
				curve.GetEndPoint(1);
				foreach (Curve curve2 in lstCurveOther)
				{
					curve2.GetEndPoint(0);
					curve2.GetEndPoint(1);
					XYZ xyz = null;
					if (FindCrossPointsHorFireZone.IsCurveCrossOnEnd(ref xyz, curve, curve2))
					{
						foreach (Curve curve3 in lstCurveTolCur)
						{
							if (lstCurveTolCur.Count == 1 || FindCrossPointsHorFireZone.IsPointOnCurveEnd(xyz, curve3))
							{
								XYZ hyendPoint = curve3.GetEndPoint(0);
								XYZ hyendPoint2 = curve3.GetEndPoint(1);
								XYZ xyz2 = hyendPoint + (hyendPoint2 - hyendPoint) / 2.0;
								xyz2 = (xyz2 - xyz).Normalize();
								xyz = CheckPointManage.Pt3ToP2(xyz);
								xyz2 = CheckPointManage.Pt3ToP2(xyz2);
								dictionary.Add(xyz, xyz2);
								break;
							}
						}
					}
				}
			}
			return dictionary;
		}

		public static bool IsPointOnCurveEnd(XYZ pt, Curve curve)
		{
			XYZ xyz = curve.GetEndPoint(0);
			XYZ xyz2 = curve.GetEndPoint(1);
			xyz = new XYZ(xyz.X, xyz.Y, 0.0);
			xyz2 = new XYZ(xyz2.X, xyz2.Y, 0.0);
			pt = new XYZ(pt.X, pt.Y, 0.0);
			double eps = YJKRevitArea.AreaSet.Common.mmToFeet(2.0);
			return Geometry.IsEqual(pt, xyz, eps) || Geometry.IsEqual(pt, xyz2, eps);
		}

		public static bool IsPointOnCurveMid(XYZ pt, Curve curve)
		{
			if (FindCrossPointsHorFireZone.IsPointOnCurveEnd(pt, curve))
			{
				return false;
			}
			XYZ xyz = curve.Project(pt).XYZPoint;
			xyz = new XYZ(xyz.X, xyz.Y, pt.Z);
			return GeoUtil.IsPointEqual(xyz, pt);
		}

		public static bool IsCurveCrossOnEnd(ref XYZ ptCross, Curve curve1, Curve curve2)
		{
			XYZ hyendPoint = curve1.GetEndPoint(0);
			XYZ hyendPoint2 = curve1.GetEndPoint(1);
			curve2.GetEndPoint(0);
			curve2.GetEndPoint(1);
			if (FindCrossPointsHorFireZone.IsPointOnCurveEnd(hyendPoint, curve2))
			{
				ptCross = hyendPoint;
				return true;
			}
			if (FindCrossPointsHorFireZone.IsPointOnCurveEnd(hyendPoint2, curve2))
			{
				ptCross = hyendPoint2;
				return true;
			}
			return false;
		}

		public static void DeleteNotOnOutWallCurves(ref List<Curve> lstCurve, List<Wall> lstOutWall)
		{
			Wall wall = null;
			for (int i = 0; i < lstCurve.Count; i++)
			{
				Curve curCurve = lstCurve[i];
				if (!FindCrossPointsHorFireZone.IsCurveOnWallOutline(ref wall, curCurve, lstOutWall))
				{
					lstCurve.RemoveAt(i);
					i--;
				}
			}
		}

		public static bool IsCurveOnWall(Curve curCurve, Wall curWall)
		{
			Curve curve = (curWall.Location as LocationCurve).Curve;
			double num = curWall.Width / 2.0;
			curCurve.GetEndPoint(0);
			curCurve.GetEndPoint(1);
			XYZ xyz = curCurve.Evaluate(0.5, true);
			XYZ xyz2 = curve.Project(xyz).XYZPoint;
			xyz = CheckPointManage.Pt3ToP2(xyz);
			xyz2 = CheckPointManage.Pt3ToP2(xyz2);
			double num2 = xyz.DistanceTo(xyz2);
			return num2 < num || object.Equals(num2, num);
		}

		public static bool IsCurveOnWallOutline(ref Wall curWall, Curve curCurve, List<Wall> lstWall)
		{
			foreach (Wall wall in lstWall)
			{
				if (FindCrossPointsHorFireZone.IsCurveOnWall(curCurve, wall))
				{
					curWall = wall;
					return true;
				}
			}
			return false;
		}

		public static void GetWallEndPoints(ref XYZ ptS, ref XYZ ptE, Wall wall)
		{
			LocationCurve locationCurve = wall.Location as LocationCurve;
			ptS = locationCurve.Curve.GetEndPoint(0);
			ptE = locationCurve.Curve.GetEndPoint(1);
		}

		public static bool IsPointOnWall(XYZ ptIn, Wall curWall)
		{
			Curve curve = (curWall.Location as LocationCurve).Curve;
			double num = curWall.Width / 2.0;
			XYZ xyz = curve.Project(ptIn).XYZPoint;
			ptIn = CheckPointManage.Pt3ToP2(ptIn);
			xyz = CheckPointManage.Pt3ToP2(xyz);
			return ptIn.DistanceTo(xyz) <= num;
		}

		public static bool IsPointOnLineWall(XYZ pt, Wall wall)
		{
			LocationCurve locationCurve = wall.Location as LocationCurve;
			XYZ hyendPoint = locationCurve.Curve.GetEndPoint(0);
			XYZ hyendPoint2 = locationCurve.Curve.GetEndPoint(1);
			double num = wall.Width / 2.0;
			XYZ xyz = new XYZ(pt.X, pt.Y, hyendPoint.Z);
			XYZ xyz2 = Geometry.CalculateFootPoint(hyendPoint, hyendPoint2, xyz);
			if (xyz.DistanceTo(xyz2) - num > FindCrossPointsHorFireZone.precision)
			{
				return false;
			}
			if (xyz2.DistanceTo(hyendPoint) < FindCrossPointsHorFireZone.precision || xyz2.DistanceTo(hyendPoint2) < FindCrossPointsHorFireZone.precision)
			{
				return true;
			}
			XYZ xyz3 = xyz2 - hyendPoint;
			XYZ xyz4 = hyendPoint2 - xyz2;
			return xyz3.Normalize().IsAlmostEqualTo(xyz4.Normalize());
		}

		public static bool IsPointOnArcWall(XYZ pt, Wall wall)
		{
			Arc arc = (wall.Location as LocationCurve).Curve as Arc;
			XYZ center = arc.Center;
			double num = wall.Width / 2.0;
			XYZ xyz = new XYZ(pt.X, pt.Y, center.Z);
			XYZ xyz2 = xyz - center;
			XYZ xyz3 = center + xyz2.Normalize() * arc.Radius;
			if (xyz.DistanceTo(xyz3) - num > FindCrossPointsHorFireZone.precision)
			{
				return false;
			}
			Line line = YJKLineEx.YJKGetBound(center, xyz3);
            return (int)arc.Intersect(line) == 8;
		}

		public static void DrawLineTemp(Autodesk.Revit.DB.Document doc, List<Curve> lstCurve)
		{
			foreach (Curve curve in lstCurve)
			{
				FindCrossPointsHorFireZone.DrawLineTemp(doc, curve.GetEndPoint(0), curve.GetEndPoint(1));
			}
		}

		public static void DrawLineTemp(Autodesk.Revit.DB.Document doc, Curve curve)
		{
			FindCrossPointsHorFireZone.DrawLineTemp(doc, curve.GetEndPoint(0), curve.GetEndPoint(1));
		}

		public static void DrawLineTemp(Autodesk.Revit.DB.Document doc, XYZ ptS, XYZ ptE)
		{
			Transaction transaction = new Transaction(doc, "ok");
			transaction.Start();
			try
			{
				Line line = Line.CreateBound(ptS, ptE);
				DetailCurve detailCurve = doc.Create.NewDetailCurve(doc.ActiveView, line);
				string text = "错位线";
				Category category = doc.Settings.Categories.get_Item(BuiltInCategory.OST_Lines);
				Category category2;
				if (category.SubCategories.Contains(text))
				{
					category2 = category.SubCategories.get_Item(text);
				}
				else
				{
					category2 = doc.Settings.Categories.NewSubcategory(category, text);
				}
				category2.LineColor = new Autodesk.Revit.DB.Color(0, byte.MaxValue, 0);
				category2.SetLineWeight(8, (Autodesk.Revit.DB.GraphicsStyleType)1);
                GraphicsStyle graphicsStyle = category2.GetGraphicsStyle((Autodesk.Revit.DB.GraphicsStyleType)1);
				if (graphicsStyle != null)
				{
					detailCurve.LineStyle = graphicsStyle;
				}
			}
			catch (Exception ex)
			{
				YJKMessageBox.Show(ex.Message);
			}
			transaction.Commit();
		}

		public static double precision = 0.001;

		private List<Wall> m_lstOutWalls;

		private Document m_curDoc;

		private ViewPlan m_curViewPlan;

		private List<Area> m_lstArea;

		private Dictionary<XYZ, XYZ> m_dictCrossPoints;

		private UIApplication m_uiApp;
	}
}
